import math
import platform
import os
from PIL import ImageFont, ImageDraw, Image
import tkinter as tk
from abc import ABC
from graphics.Shape import Shape
from tkinter import font as tkFont
import numpy as np


class TextBox(Shape):
    def __init__(self, x, y, text="Text", font_size=12,
                 font_family="Arial",  ** kwargs):
        """

        :param x: 文本中心x
        :param y: 文本中心y
        :param text: 文本内容
        :param font_size: 字体大小
        :param font_family: 字体
        :param kwargs:
        """
        super().__init__(**kwargs)
        self.text = text
        self.x = x
        self.y = y
        self.font_size = font_size
        self.font_family = font_family
        self.editing = False  # 新增编辑状态标记
        self.entry_widget = None  # 新增Entry控件引用
        self.text_offset = (0, 0)  # 文本绘制偏移量

        # 新增系统字体路径自动检测
        if font_family is None:
            self.font_family = self._get_system_font("Arial")
        elif not os.path.exists(font_family):
            self.font_family = self._find_font_path(font_family)
        else:
            self.font_family = font_family

    def draw(self, canvas):
        # print(f"self.__class__.__name__:{self.__class__.__name__};type is {type(self.__class__.__name__)}")
        """实现文本绘制逻辑（支持动态编辑）"""
        if self.editing:
            self._draw_editable(canvas) # 编辑模式
            self.editing = False
        else:
            self._draw_static(canvas)   # 静态显示模式

        if self.selected:
            self._draw_selection_box(canvas)

    def _draw_selection_box(self, canvas):
        """
        绘制选择框和控制点
        :param canvas:
        :return:
        """

        bbox = self.get_bounding_box()
        # 绘制虚线包围盒
        canvas.create_rectangle(
            bbox[0], bbox[1], bbox[2], bbox[3],
            outline='#2196F3', dash=(4, 2), tags="selection"
        )
        # 绘制移动控制点（中心点）
        handle_size = 8
        center_x = (bbox[0] + bbox[2]) / 2
        center_y = (bbox[1] + bbox[3]) / 2
        canvas.create_oval(
            center_x - handle_size, center_y - handle_size,
            center_x + handle_size, center_y + handle_size,
            fill='#2196F3', tags="handle"
        )

    def _draw_static(self, canvas):
        """
        静态文本绘制
        :param canvas:
        :return:
        """
        font = tkFont.Font(family=self.font_family, size=self.font_size)

        # 应用仿射变换获取实际绘制位置
        transformed_pos = self._apply_transform((self.x, self.y))

        # 强制使用中心锚点
        canvas.create_text(
            transformed_pos[0],  # 直接使用中心点X
            transformed_pos[1],  # 直接使用中心点Y
            text=self.text,
            fill=self.color,
            font=(self.font_family, self.font_size),
            anchor=tk.CENTER  # 关键修改
        )

    def _draw_editable(self, canvas):
        """
        编辑模式下的文本绘制（创建Entry控件）
        :param canvas:
        :return:
        """
        if not self.entry_widget:
            # 创建Entry控件
            self.entry_widget = tk.Entry(
                canvas,
                font=(self.font_family, self.font_size),
                bg='white', fg=self.color,
                relief='groove',  # 边框样式（可选：flat/sunken/raised/groove/ridge）
                highlightthickness=2,  # 边框厚度
                highlightbackground="#666666",  # 默认边框颜色
                highlightcolor="#2196F3"  # 焦点时边框颜色（如蓝色）
            )
            # 计算并设置控件位置
            current_pos = self._apply_transform((self.x, self.y))
            self.entry_widget.place(
                x=current_pos[0] - 50,
                y=current_pos[1] - 15,
                width=100, height=30
            )
            # 初始化控件内容
            self.entry_widget.insert(0, self.text)
            self.entry_widget.focus_set()
            # 绑定事件
            self.entry_widget.bind("<Return>", self._finish_editing)
            self.entry_widget.bind("<FocusOut>", self._finish_editing)

            # 调试用基准线
            canvas.create_line(current_pos[0] - 10, current_pos[1],
                               current_pos[0] + 10, current_pos[1], fill='red')  # 水平线
            canvas.create_line(current_pos[0], current_pos[1] - 10,
                               current_pos[0], current_pos[1] + 10, fill='red')  # 垂直线

    def _finish_editing(self, event=None):
        """
        结束编辑状态
        保存文本内容
        :param event:
        :return:
        """
        if self.entry_widget:
            self.text = self.entry_widget.get()# 获取编辑后的文本
            self.entry_widget.destroy()# 销毁控件
            self.entry_widget = None
        self.editing = False # 退出编辑模式

    def _find_font_path(self, font_name):
        """
        搜索系统字体目录
        :param font_name:
        :return:
        """
        try:
            from matplotlib import font_manager
            prop = font_manager.FontProperties(family=font_name)
            return font_manager.findfont(prop)
        except ImportError:
            return self._get_system_font(font_name)

    @staticmethod
    def _get_system_font(font_name):
        """
        根据系统自动获取字体路径
        :param font_name:
        :return:
        """
        system = platform.system()
        if system == "Windows":
            return r"C:\Windows\Fonts\{}.ttf".format(font_name)
        elif system == "Linux":
            return "/usr/share/fonts/truetype/freefont/FreeSans.ttf"
        elif system == "Darwin":
            return "/Library/Fonts/Arial.ttf"
        return "arial.ttf"  # 保底值

    def get_text_size(self):
        """
        计算文本的尺寸（宽高）
        :return: (width, height) 元组
        """

        try:
            if not os.path.exists(self.font_family):
                raise FileNotFoundError(f"字体文件 {self.font_family} 不存在")

            # 使用Tkinter原生字体测量方法
            font = tkFont.Font(family=self.font_family, size=self.font_size)
            text_width = font.measure(self.text)
            text_height = font.metrics("linespace") * 1.2  # 增加行间距补偿

            # 增加边框补偿
            return text_width + 4, text_height + 4

        except (OSError, IOError) as e:
            print(f"字体加载失败: {e}, 使用备用字体")
            backup_font = self._get_system_font("Arial")
            pil_font = ImageFont.truetype(backup_font, self.font_size)
            bbox = pil_font.getbbox(self.text)
            return bbox[2] - bbox[0] + 4, bbox[3] - bbox[1] + 4

    def get_bounding_box(self):
        """
        获取文本框的包围盒（考虑变换）
        :return: (x1, y1, x2, y2) 元组
        """
        text_width, text_height = self.get_text_size()

        # 原始包围盒（以中心为基准）
        raw_bbox = (
            self.x - text_width / 2,  # 左边界
            self.y - text_height / 2,  # 上边界
            self.x + text_width / 2,  # 右边界
            self.y + text_height / 2  # 下边界
        )

        # 应用text_offset到变换后的坐标
        offset_matrix = [
            1, 0,
            0, 1,
            self.text_offset[0],
            self.text_offset[1]
        ]

        # 合并变换矩阵
        combined_matrix = self._combine_matrices(
            self.transform_matrix,
            offset_matrix
        )

        # 转换顶点时使用合并矩阵,变换四个角点
        corners = [(raw_bbox[0], raw_bbox[1]), (raw_bbox[2], raw_bbox[1]),
                   (raw_bbox[2], raw_bbox[3]), (raw_bbox[0], raw_bbox[3])]
        transformed = [self._apply_transform_with_matrix(p, combined_matrix)
                       for p in corners]

        return (
            min(p[0] for p in transformed),
            min(p[1] for p in transformed),
            max(p[0] for p in transformed),
            max(p[1] for p in transformed)
        )

    def _combine_matrices(self, m1, m2):
        """
        合并两个变换矩阵
        :param m1: 第一个矩阵
        :param m2: 第二个矩阵
        :return: 合并后的矩阵
        """
        return [
            m1[0] * m2[0] + m1[1] * m2[2],
            m1[0] * m2[1] + m1[1] * m2[3],
            m1[2] * m2[0] + m1[3] * m2[2],
            m1[2] * m2[1] + m1[3] * m2[3],
            m1[4] * m2[0] + m1[5] * m2[2] + m2[4],
            m1[4] * m2[1] + m1[5] * m2[3] + m2[5]
        ]

    def _apply_transform_with_matrix(self, point, matrix):
        """
        应用指定变换矩阵到点
        :param point: (x,y)坐标
        :param matrix: 变换矩阵
        :return: 变换后的坐标
        """
        x = point[0] * matrix[0] + point[1] * matrix[1] + matrix[4]
        y = point[0] * matrix[2] + point[1] * matrix[3] + matrix[5]
        return (x, y)

    def contains(self, x, y):
        """
        检查点是否在文本框内
        :param x: 点x坐标
        :param y: 点y坐标
        :return: True/False
        """
        bbox = self.get_bounding_box()
        return (bbox[0] <= x <= bbox[2]) and (bbox[1] <= y <= bbox[3])


    def resize(self,dx,dy):
        pass


    def to_dict(self):
        # print("I'm textbox")
        """增强版序列化（包含字体信息）"""
        data = super().to_dict()
        data.update({
            "text": self.text,
            "x": self.x,
            "y": self.y,
            "font_size": self.font_size,
            "font_family": self.font_family,
            "type": "TextBox"
        })
        return data

    @classmethod
    def from_dict(cls, data):
        """支持字体反序列化"""
        return cls(
            x=data["x"],
            y=data["y"],
            text=data["text"],
            font_size=data["font_size"],
            font_family=data["font_family"],
            color=data["color"],
            line_width=data["line_width"],
            transform=data["transform"],
            fill=data.get("fill", data["color"]),
            auto_fill=data.get("auto_fill", False)
        )

    def start_edit(self):
        """
        进入编辑模式
        :return:
        """
        self.editing = True

    def move(self, dx, dy):
        """
        移动文本框
        :param dx: x方向位移
        :param dy: y方向位移
        """
        # 将位移转换为矩阵运算
        move_matrix = [
            1, 0,
            0, 1,
            dx / self.transform_matrix[0],  # 考虑缩放因子
            dy / self.transform_matrix[3]
        ]

        # 合并到当前变换矩阵
        self.transform_matrix = self._combine_matrices(
            self.transform_matrix,
            move_matrix
        )

    def _update_entry_position(self):
        if self.entry_widget:
            # 获取最新变换后的坐标
            current_pos = self._apply_transform((self.x, self.y))
            # 动态计算控件尺寸
            width = self.entry_widget.winfo_reqwidth()
            height = self.entry_widget.winfo_reqheight()
            self.entry_widget.place_configure(
                x=current_pos[0] - width / 2,  # 水平居中
                y=current_pos[1] - height / 2  # 垂直居中
            )

    def _apply_transform(self, point):
        """完整仿射变换矩阵计算"""
        x = point[0] * self.transform_matrix[0] + \
            point[1] * self.transform_matrix[1] + \
            self.transform_matrix[4]
        y = point[0] * self.transform_matrix[2] + \
            point[1] * self.transform_matrix[3] + \
            self.transform_matrix[5]
        return (x, y)

    def rotate(self, angle):
        super().rotate(angle)
        if self.editing:
            self._update_entry_position()  # 旋转后同步位置


